#ifndef PIPELINE_H
#define PIPELINE_H

#include "Include.h"
#include "Logger.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "RenderTarget.h"
#include "DepthBuffer.h"
#include "TextureFactory.h"
#include "ConstantBuffer.h"
#include "PipelineStates.h"

namespace devii
{

	enum BlendStates
	{
		NONE = 0,
		ADDITIVE_BLENDING = 1,
	};

	enum RasterizerStates
	{
		WIRE_FRAME_ON = 0,
		WIRE_FRAME_OFF = 1,
	};

	enum SamplerStates
	{
		DEFAULT = 0,

	};

class Pipeline
{
public:
	Pipeline();
	~Pipeline();

	bool			startupD3D(const int & width, const int & height, HWND hwnd);
	bool			shutdown();

	void			draw(const unsigned int start, const unsigned int nr_of_vertices);

	void			swap();

	void			setRenderTarget(const unsigned int nr_rendertargets, RenderTarget ** render_target, DepthBuffer * depth);

	void			setVertexBuffer(VertexBuffer * const vertex_buffer);
	void			setIndexBuffer(IndexBuffer * const index_buffer);
	void			setVertexShader(ID3D11VertexShader* const vertex_shader);
	void			setHullShader(ID3D11HullShader* const hull_shader);
	void			setDomainShader(ID3D11DomainShader* const domain_shader);
	void			setGeometryShader(ID3D11GeometryShader* const geometry_shader);
	void			setPixelShader(ID3D11PixelShader* const pixel_shader);
	void			setViewports(unsigned int nr_viewports, D3D11_VIEWPORT* view_ports);

	void			setupPipeline(PipelineStates* const states);
	void			clearRenderTarget(float clear_color[], RenderTarget * const render_target);
	void			clearDepthBuffer(DepthBuffer* const depth_buffer);

	VertexBuffer*	createVertexBuffer();
	IndexBuffer*	createIndexBuffer();
	ConstantBuffer*	createConstantBuffer();
	Texture*		createTexture(const unsigned int width, const unsigned int height, DXGI_FORMAT color_format);
	Texture*		createTexture(const std::string& file);
	RenderTarget*	createScreenRenderTarget(const unsigned int width, const unsigned int height);
	RenderTarget*	createTextureRenderTarget(const unsigned int width, const unsigned int height);
	DepthBuffer*	createDepthBuffer(const unsigned int width, const unsigned int height);
	PipelineStates*	createPipelineStates();

	ID3D11VertexShader*		createVertexShader(const std::string& file, const std::string& function, 
												VertexBuffer * const buffer, D3D11_INPUT_ELEMENT_DESC* input_desc, 
												const int nr_of_elements);

	ID3D11HullShader*		createHullShader(const std::string& file, const std::string& function);
	ID3D11DomainShader*		createDomainShader(const std::string& file, const std::string& function);
	ID3D11GeometryShader*	createGeometryShader(const std::string& file, const std::string& function);
	ID3D11PixelShader*		createPixelShader(const std::string& file, const std::string& function);
	//ID3D11InputLayout*		createInputLayout(
private:
	ID3D11Device * device;
	ID3D11DeviceContext * context;
	IDXGISwapChain * swapchain;
	
	std::vector<VertexBuffer*> vertex_buffers;
	std::vector<IndexBuffer*> index_buffers;
	
	D3D_FEATURE_LEVEL feature_level;


	// Factories

	TextureFactory texture_factory;

};

}

#endif